home *** CD-ROM | disk | FTP | other *** search
- /* automatic persistence setting for ax.25 interfaces */
-
- #include "global.h"
- #include "ax25.h"
- #include "iface.h"
- #include "persist.h"
- #include "timer.h"
-
- static struct persist *pblk; /* list of persistence cb's */
- static struct timer p_timer;
- static void tick_ptimer();
- extern char nospace[],notax25[];
-
- /* set/show automatic persistence calculation parameters */
- int
- dopersist(argc,argv)
- int argc;
- char *argv[];
- {
- register struct persist *pp;
- struct interface *ifp;
-
- if (argc == 1){ /* no args - show parms */
- printf("IF Users P P0 Pmin Pmax Tinc Tmax\n");
-
- for (pp = pblk; pp != NULLPERSIST; pp = pp->next)
- printf("%-6s%5d%5d%5d%6d%6d%6d%6d\n",pp->iface->name,
- pp->n_users,pp->p,pp->p0,pp->p_min,pp->p_max,
- pp->pt_incr * PT_INTER,pp->pt_max * PT_INTER);
-
- return 0;
- }
-
- if ((ifp = ifunit(argv[1])) == NULLIF)
- return 1;
-
- if (!(ifp->flags & IF_AX25)){
- printf(notax25,argv[1]);
- return 1;
- }
-
- stop_timer(&p_timer);
-
- for (pp = pblk; pp != NULLPERSIST; pp = pp->next)
- if (pp->iface == ifp) /* lookup by interface */
- break;
-
- if (pp == NULLPERSIST){ /* if not in list? */
- if ((pp = (struct persist *) calloc(1,sizeof(struct persist))) == NULLPERSIST){
- printf(nospace);
- if (pblk != NULLPERSIST)
- start_timer(&p_timer);
- return 1;
- }
-
- if ((pp->next = pblk) != NULLPERSIST)
- pp->next->prev = pp;
-
- pblk = pp;
- pp->iface = ifp;
- pp->p0 = P0;
- pp->p_min = P_MIN;
- pp->p_max = pp->p = P_MAX;
- pp->pt_incr = PT_INCR;
- pp->pt_max = PT_MAX;
- }
-
- /* set control values, delete cb when p0 value is 0 (or "off") */
-
- if (argc > 2)
- if ((pp->p0 = atoi(argv[2])) == 0){
- if (pp->prev != NULLPERSIST)
- pp->prev->next = pp->next;
- else
- pblk = pp->next;
-
- if (pp->next != NULLPERSIST)
- pp->next->prev = pp->prev;
-
- free(pp);
- }
-
- if (argc > 3)
- pp->p_min = atoi(argv[3]);
-
- if (argc > 4)
- pp->p_max = atoi(argv[4]);
-
- if (argc > 5)
- pp->pt_incr = atoi(argv[5]) / PT_INTER;
-
- if (argc > 6)
- pp->pt_max = atoi(argv[6]) / PT_INTER;
-
- /* (re)start the timer only if any persistence cb's left */
-
- if (pblk != NULLPERSIST){
- p_timer.start = SEC2TICK(PT_INTER);
- p_timer.func = tick_ptimer;
- tick_ptimer();
- }
- return 0;
- }
-
- /* update the "number of users" for an interface when a callsign is heard */
- /* the ssid is not considered significant */
-
- int
- upd_nusers (ifp,call)
- struct interface *ifp;
- register unsigned char *call;
-
- {
- register struct persist *pp;
- register unsigned hashval;
- register int i;
-
- for (pp = pblk; pp != NULLPERSIST; pp = pp->next)
- if (pp->iface == ifp) /* lookup by interface */
- break;
-
- if (pp == NULLPERSIST) /* if not in list? */
- return -1; /* return soft failure */
-
- hashval = 0;
- for (i = 0; i < ALEN; i++) /* scan callsign (not SSID) */
- hashval = (hashval << 1) ^ (*call++ & 0xfe);
-
- hashval %= (unsigned) SLOTS;
-
- if ((pp->heard[hashval] += pp->pt_incr) > pp->pt_max)
- pp->heard[hashval] = pp->pt_max;
-
- return 0; /* ok */
- }
-
- /* tick the "automatic persistence" timer, decrementing the timers and */
- /* re-computing the number of users on each channel. when changed, set */
- /* the persistence value for that channel. */
-
- static void
- tick_ptimer ()
-
- {
- register struct persist *pp;
- register unsigned i,n_users,p;
- static char *argv[3] = {"2","###",NULLCHAR};
-
- for (pp = pblk; pp != NULLPERSIST; pp = pp->next){
- n_users = 0;
- for (i = 0; i < SLOTS; i++)
- if (pp->heard[i]){
- pp->heard[i]--;
- n_users++; /* count the active users */
- }
-
- if ((pp->n_users = n_users) == 0)
- p = pp->p0;
- else
- p = pp->p0 / n_users;
-
- if (p > pp->p_max) /* keep p within p_min .. p_max */
- p = pp->p_max;
-
- if (p < pp->p_min)
- p = pp->p_min;
-
- if (pp->p != p){ /* a change in p value? */
- sprintf(argv[1],"%d",pp->p = p); /* convert to string */
- if (pp->iface->ioctl != NULLFP)
- (*pp->iface->ioctl)(pp->iface,2,argv); /* set p value */
- }
- }
-
- start_timer(&p_timer); /* restart the timer */
- }
-